﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EasyQuartz.Domain.Scheduler;
using EasyQuartz.Domain.Jobs;
using Quartz;
using Quartz.Impl;
using System.Collections.Specialized;
using System.Configuration;
using System.Reflection;

namespace EasyQuartz.Domain.Services.Scheduling
{
	public class SchedulingManager : ISchedulingManager
	{
		private static ISchedulerFactory sf = new StdSchedulerFactory(GetProperties());
		private static IScheduler sched = sf.GetScheduler();

		#region ISchedulingManager Members

		public void Start()
		{
			sched.Start();
		}

		public void Stop()
		{
			sched.Shutdown();
		}

		public void RunJob(string jobName, string jobGroup)
		{
			SimpleTrigger trigger = new SimpleTrigger("Inmediatly->" + jobName + "|" + jobGroup);

			// Check run now
			JobDetail jobDetail = sched.GetJobDetail(jobName, jobGroup);
			JobDetail toExecute = new JobDetail { Name = jobName, Group = "Inmediatly", JobType = jobDetail.JobType, Description = jobDetail.Description };

			if (sched.GetJobDetail(toExecute.Name, toExecute.Group) == null)
				sched.ScheduleJob(toExecute, trigger);
		}

		public void AddJob(JobDetail detail, Trigger trigger)
		{
			sched.ScheduleJob(detail, trigger);
		}

		public void AddJob(string jobName, string jobGroup, string cronExpression, string jobType)
		{
			JobDetail detail = new JobDetail
			{
				Name = jobName,
				Group = jobGroup,
				JobType = Type.GetType(jobType)
			};

			CronTrigger trigger = new CronTrigger(jobName, jobGroup, cronExpression);

			AddJob(detail, trigger);
		}

		public void StopJob(int jobId)
		{
			sched.Shutdown();
		}

		public EasySchedulerStatus Status
		{
			get
			{
				if (sched.GetMetaData().Started)
					return EasySchedulerStatus.Active;
				else if (sched.GetMetaData().Shutdown)
					return EasySchedulerStatus.Down;
				else if (sched.GetMetaData().InStandbyMode)
					return EasySchedulerStatus.Inactive;

				throw new ApplicationException("Server status unknow. ");
			}
		}

		public static List<JobDetail> GetJobDetails()
		{
			List<JobDetail> jobDetails = new List<JobDetail>();
			var jobGroupNames = sched.JobGroupNames;
			foreach (var jobGroupName in jobGroupNames)
			{
				var jobNames = sched.GetJobNames(jobGroupName);

				foreach (var jobName in jobNames)
				{
					var details = sched.GetJobDetail(jobName, jobGroupName);
					jobDetails.Add(details);
				}
			}
			return jobDetails;
		}

		public List<EasyJob> Jobs
		{
			get
			{
				var easyJobs = new List<EasyJob>();

				foreach (var item in GetJobDetails())
					easyJobs.Add(new EasyJob { Name = item.Name, Group = item.Group, Type = item.JobType.FullName });

				return easyJobs;
			}
		}

		#endregion

		/// <summary>
		/// Get the properties to quartz config.
		/// </summary>
		/// <returns></returns>
		private static NameValueCollection GetProperties()
		{
			Configuration configuration;

			if (ConfigurationManager.OpenExeConfiguration(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath).HasFile)
				configuration = ConfigurationManager.OpenExeConfiguration(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);
			else
				configuration = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);

			NameValueCollection properties = new NameValueCollection();
			foreach (KeyValueConfigurationElement item in configuration.AppSettings.Settings)
				properties[item.Key] = item.Value;

			return properties;
		}

	}
}
